home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1990 September: Essentials 4 / ADC Developer CD (1990-09) [Essentials 4]_iso / Developer Essentials 4.iso / d e v e l o p / develop 4 code / A:ROSE / ClientAppliƒ / ClientAppli.c / ClientAppli.c
Encoding:
C/C++ Source or Header  |  1990-08-28  |  19.0 KB  |  821 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2. #
  3. #    ClientAppli.c
  4. #
  5. #    derived from MPW 3.1's "Sample", a MultiFinder-Aware Simple Sample Application
  6. #
  7. #   Demostrates how to communicate with A/ROSE tasks 
  8. #
  9. #   Refer to the original source code in the MPW CExamples folder for more comments
  10. #
  11. #    Components:
  12. #                ClientAppli.c
  13. #                ClientAppli.r
  14. #                ClientAppli.h
  15. #                ClientAppli.make
  16. #
  17. #  MPW build commands:
  18. #
  19.         C ClientAppli.c
  20.         Link ClientAppli.c.o ∂
  21.             "{CLibraries}"CRuntime.o ∂
  22.             "{CLibraries}"CInterface.o ∂
  23.             "{Libraries}"Interface.o ∂
  24.             "{AROSEPrep}"IPCGlue.o ∂
  25.             -o ClientAppli 
  26.         Rez -rd -o ClientAppli ClientAppli.r -append
  27. #
  28. ------------------------------------------------------------------------------*/
  29.  
  30.  
  31.  
  32. #include <Types.h>
  33. #include <Resources.h>
  34. #include <QuickDraw.h>
  35. #include <Fonts.h>
  36. #include <Events.h>
  37. #include <Windows.h>
  38. #include <Menus.h>
  39. #include <TextEdit.h>
  40. #include <Dialogs.h>
  41. #include <Desk.h>
  42. #include <ToolUtils.h>
  43. #include <Memory.h>
  44. #include <SegLoad.h>
  45. #include <Files.h>
  46. #include <OSUtils.h>
  47. #include <OSEvents.h>
  48. #include <DiskInit.h>
  49. #include <Packages.h>
  50. #include <Traps.h>
  51. #include <Strings.h>
  52.  
  53. #include "ClientAppli.h"    // bring in all the #defines for ClientAppli
  54.  
  55. //---------------------------------------------------------------------------
  56. // A/ROSE declarations (from "os.h"):
  57.  
  58. typedef long    tid_type;
  59.  
  60. struct mMessage
  61. {
  62.     struct    mMessage    *mNext;
  63.     long                mId;
  64.     short                mCode;
  65.     short                mStatus;
  66.     unsigned    short    mPriority;
  67.     tid_type            mFrom;
  68.     tid_type            mTo;
  69.     unsigned    long    mSData [3];
  70.     unsigned    long    mOData [3];
  71.     long                mDataSize;        // Size of data buffer in bytes. set to negative 
  72.                                         // size of buffer if buffer is shared
  73.                                         // between tasks. eg. Buffer cannot be copied 
  74.     char                *mDataPtr;
  75. };
  76.  
  77. typedef struct mMessage mMessage;
  78.  
  79. #define    OS_MATCH_ALL    0        // on receive match anything
  80. #define    OS_NO_TIMEOUT    0        // receive waits forever for message
  81.  
  82. // and some #define's from "managers.h":
  83.  
  84. #define    OS_UNKNOWN_MESSAGE        (1<<8)    // unknown message                    
  85. #define    Machine_Visible            0        // Register_task Machine visible flag    
  86.  
  87. #define    ICC_GETCARDS    150        // Get list of active cards and their name mgr TID
  88.  
  89. //---------------------------------------------------------------------------
  90.  
  91.  
  92. // global variables 
  93.  
  94. SysEnvRec    gMac;                // set up by Initialize 
  95. Boolean        gHasWaitNextEvent;    // set up by Initialize 
  96. Boolean        gInBackground;        // maintained by Initialize and DoEvent 
  97. long        gSleepVal;            // MultiFinder sleep value
  98.                                 // for WaitNextEvent
  99.  
  100. short        gReceived;          // number of received/sent messages 
  101. short        gSent;
  102. tid_type    gTID,                // my task identifier returned by OpenQueue() 
  103.             gServerTID;            // the task identifier of the required server task 
  104.             
  105. WindowPtr    gMyWindow;            // only one window 
  106. ControlHandle ghReset, ghSend;    // two buttons in the window 
  107.  
  108. tid_type      gCards[16];            // array of Name Manager TID's in NuBus slots
  109.  
  110. // Prototypes for parameter type checking. 
  111.  
  112. void EventLoop( void );
  113. void DoEvent( EventRecord *event );
  114. void DoUpdate( WindowPtr window );
  115. void DoActivate( WindowPtr window, Boolean becomingActive );
  116. void DoContentClick( WindowPtr window, EventRecord *event);
  117. void DrawWindow( WindowPtr window );
  118. void AdjustMenus( void );
  119. void DoMenuCommand( long menuResult );
  120. Boolean DoCloseWindow( WindowPtr window );
  121. void Terminate( void );
  122. void Initialize( void );
  123. void ForceEnvirons( void );
  124. Boolean IsAppWindow( WindowPtr window );
  125. Boolean IsDAWindow( WindowPtr window );
  126. Boolean TrapAvailable( short tNumber, TrapType tType );
  127. void AlertUser( short error );
  128. void BigBadError( short error );
  129. void NumToHex( long n, short d, char *s);
  130. short AROSEPrep();
  131. tid_type FindServer(char *name, char *type);
  132. Boolean AskICCM();
  133. void TaskProcessing();
  134. void SendaMessage(short msgCode, tid_type msgDest);
  135. void UpdateDisplay();
  136.  
  137. // A/ROSE prototypes: --------------------
  138.  
  139. extern     char        Register_Task(char *, char *, short);
  140. extern    mMessage    *GetMsg(void);
  141. extern    mMessage    *Receive();
  142. extern     void        SwapTID(mMessage *);
  143. extern    void        Send(mMessage *);
  144. extern  void        FreeMsg();
  145.  
  146. extern    tid_type    GetTID(void);
  147. extern    tid_type    GetICCTID(void);
  148. extern    tid_type    Lookup_Task(char *, char *, tid_type, unsigned short *);
  149.  
  150. extern    tid_type    OpenQueue();
  151. extern    void        CloseQueue();
  152. //----------------------------------------
  153.  
  154. // Define HiWrd and LoWrd macros for efficiency. 
  155. #define HiWrd(aLong)    (((aLong) >> 16) & 0xFFFF)
  156. #define LoWrd(aLong)    ((aLong) & 0xFFFF)
  157.  
  158.  
  159. extern void _DataInit();
  160.  
  161.  
  162. #pragma segment Main
  163. main()
  164. {
  165.     UnloadSeg((Ptr) _DataInit);        // note that _DataInit must not be in Main! 
  166.     
  167.     MaxApplZone();                    // expand the heap so code segments load at the top 
  168.  
  169.     Initialize();                    // initialize the program 
  170.     UnloadSeg((Ptr) Initialize);    // note that Initialize must not be in Main! 
  171.  
  172.     EventLoop();                    // call the main event loop 
  173. }
  174.  
  175.  
  176. #pragma segment Main
  177. void EventLoop()
  178. {
  179.     Boolean        gotEvent;
  180.     EventRecord    event;
  181.  
  182.     do {
  183.             gotEvent = WaitNextEvent(everyEvent, &event, gSleepVal, nil);
  184.         if ( gotEvent )
  185.             DoEvent(&event);
  186.  
  187. //=========================            
  188.         TaskProcessing();  // <<<<<<<<<< this is the A/ROSE task !
  189. //=========================            
  190.         
  191.     } while ( true );    // loop forever; we quit via Terminate/ExitToShell 
  192. } //EventLoop
  193.  
  194.  
  195. #pragma segment Main
  196. void DoEvent(event)
  197.     EventRecord    *event;
  198. {
  199.     short        part, err;
  200.     WindowPtr    window;
  201.     char        key;
  202.     Point        aPoint;
  203.  
  204.     switch ( event->what ) {
  205.         case mouseDown:
  206.             part = FindWindow(event->where, &window);
  207.             switch ( part ) {
  208.                 case inMenuBar:                // process a mouse menu command (if any) 
  209.                     AdjustMenus();
  210.                     DoMenuCommand(MenuSelect(event->where));
  211.                     break;
  212.                 case inSysWindow:            // let the system handle the mouseDown 
  213.                     SystemClick(event, window);
  214.                     break;
  215.                 case inContent:
  216.                     if ( window != FrontWindow() ) {
  217.                         SelectWindow(window);
  218.                     } else
  219.                         DoContentClick(window, event);
  220.                     break;
  221.                 case inDrag:                // pass screenBits.bounds to get all gDevices 
  222.                     DragWindow(window, event->where, &qd.screenBits.bounds);
  223.                     break;
  224.             }
  225.             break;
  226.         case keyDown:
  227.         case autoKey:                        // check for menukey equivalents 
  228.             key = event->message & charCodeMask;
  229.             if ( event->modifiers & cmdKey )            // Command key down 
  230.                 if ( event->what == keyDown ) {
  231.                     AdjustMenus();                        // enable/disable/check menu items properly 
  232.                     DoMenuCommand(MenuKey(key));
  233.                 }
  234.             break;
  235.         case activateEvt:
  236.             DoActivate((WindowPtr) event->message, (event->modifiers & activeFlag) != 0);
  237.             break;
  238.         case updateEvt:
  239.             DoUpdate((WindowPtr) event->message);
  240.             break;        
  241.         case diskEvt:
  242.             if ( HiWord(event->message) != noErr ) {
  243.                 SetPt(&aPoint, kDILeft, kDITop);
  244.                 err = DIBadMount(aPoint, event->message);
  245.                 // so that the user can format a floppy. 
  246.             }
  247.             break;
  248.         case kOSEvent:
  249.             switch ((event->message >> 24) & 0x0FF) {        // high byte of message 
  250.                 case kSuspendResumeMessage:        // suspend/resume is also an activate/deactivate 
  251.                     gInBackground = (event->message & kResumeMask) == 0;
  252.                     DoActivate(FrontWindow(), !gInBackground);
  253.                     break;
  254.             }
  255.             break;
  256.     }
  257. } //DoEvent
  258.  
  259.  
  260. #pragma segment Main
  261. void DoUpdate(window)
  262.     WindowPtr    window;
  263. {
  264.     if ( IsAppWindow(window) ) {
  265.         BeginUpdate(window);                // this sets up the visRgn 
  266.         if ( ! EmptyRgn(window->visRgn) )    // draw if updating needs to be done 
  267.             DrawWindow(window);
  268.         EndUpdate(window);
  269.     }
  270. } //DoUpdate
  271.  
  272.  
  273. #pragma segment Main
  274. void DoActivate(window, becomingActive)
  275.     WindowPtr    window;
  276.     Boolean        becomingActive;
  277. {
  278.     if ( IsAppWindow(window) ) {
  279.         if ( becomingActive )
  280.             ; // do whatever you need to at activation
  281.         else
  282.             ; // do whatever you need to at deactivation
  283.     }
  284. } //DoActivate
  285.  
  286. #pragma segment Main
  287. void DoContentClick(window, event)
  288.     WindowPtr    window;
  289.     EventRecord    *event;
  290. {
  291.     Point    mouse;
  292.     ControlHandle control;
  293.     short    dummy;
  294.     
  295.     if ( IsAppWindow(window) ) {
  296.         SetPort(window);
  297.         mouse = event->where;                            // get the click position 
  298.         GlobalToLocal(&mouse);
  299.         if ( FindControl(mouse, window, &control) == inButton) {
  300.             dummy = TrackControl(control, mouse, nil);
  301.             if (control == ghReset) {
  302.                 SendaMessage(RESETCODE,gServerTID);
  303.                 gReceived = 0;
  304.                 gSent = 0;
  305.                 }
  306.             else if (control == ghSend)  // what else ?
  307.                 SendaMessage(DUMMYCODE, gServerTID);
  308.         }
  309.     }
  310. } //DoContentClick
  311.  
  312.  
  313. #pragma segment Main
  314. void DrawWindow(window)
  315.     WindowPtr    window;
  316. {
  317.     Str255     s;
  318.     Rect    countRect;
  319.     GrafPtr    savePort;
  320.     
  321.     GetPort(&savePort);
  322.     
  323.     SetPort(window);
  324.     TextFont(monaco);
  325.     TextSize(12);
  326.  
  327.     SetRect(&countRect,150,80,200,125);
  328.     EraseRect(&countRect);    // reduce the flicker ... 
  329.                                     
  330.     GetIndString(s, rWndStrings, 1);
  331.     MoveTo(20,20);
  332.     DrawString(s);
  333.     NumToHex(gTID, 8, s);
  334.     DrawString(s);
  335.     
  336.     GetIndString(s, rWndStrings, 2);
  337.     MoveTo(20,40);
  338.     DrawString(s);
  339.     
  340.     GetIndString(s, rWndStrings, 5);    // funny numbering scheme - compare TaskSample.r ...
  341.     MoveTo(20,70);
  342.     DrawString(s);
  343.     NumToHex(gServerTID, 8, s);
  344.     DrawString(s);
  345.     
  346.     GetIndString(s, rWndStrings, 3);
  347.     MoveTo(20,100);
  348.     DrawString(s);
  349.     NumToString(gReceived, s);
  350.     DrawString(s);
  351.  
  352.     GetIndString(s, rWndStrings, 4);
  353.     MoveTo(20,120);
  354.     DrawString(s);
  355.     NumToString(gSent, s);
  356.     DrawString(s);
  357.     
  358.     DrawControls(window);
  359.     SetPort(savePort);
  360.  
  361. } //DrawWindow
  362.  
  363.  
  364. #pragma segment Main
  365. void AdjustMenus()
  366. {
  367.     WindowPtr    window;
  368.     MenuHandle    menu;
  369.  
  370.     window = FrontWindow();
  371.  
  372.     menu = GetMHandle(mFile);
  373.     if ( IsDAWindow(window) )        // we can allow desk accessories to be closed from the menu 
  374.         EnableItem(menu, iClose);
  375.     else
  376.         DisableItem(menu, iClose);    // but not our only window 
  377.  
  378.     menu = GetMHandle(mEdit);
  379.     if ( IsDAWindow(window) ) {        // a desk accessory might need the edit menu… 
  380.         EnableItem(menu, iUndo);
  381.         EnableItem(menu, iCut);
  382.         EnableItem(menu, iCopy);
  383.         EnableItem(menu, iClear);
  384.         EnableItem(menu, iPaste);
  385.     } else {                        // …but we don’t use it 
  386.         DisableItem(menu, iUndo);
  387.         DisableItem(menu, iCut);
  388.         DisableItem(menu, iCopy);
  389.         DisableItem(menu, iClear);
  390.         DisableItem(menu, iPaste);
  391.     }
  392.     menu = GetMHandle(mSleep);
  393.     if (gSleepVal == 0) {
  394.         CheckItem(menu,iNoSleep,true);
  395.         CheckItem(menu,i60Ticks,false);
  396.     }
  397.     else  {
  398.         CheckItem(menu,iNoSleep,false);
  399.         CheckItem(menu,i60Ticks,true);
  400.     }
  401. } //AdjustMenus
  402.  
  403.  
  404. #pragma segment Main
  405. void DoMenuCommand(menuResult)
  406.     long        menuResult;
  407. {
  408.     short        menuID;                // the resource ID of the selected menu 
  409.     short        menuItem;            // the item number of the selected menu 
  410.     short        itemHit;
  411.     Str255        daName;
  412.     short        daRefNum;
  413.     Boolean        handledByDA;
  414.  
  415.     menuID = HiWord(menuResult);    // use macros for efficiency to... 
  416.     menuItem = LoWord(menuResult);    // get menu item number and menu number 
  417.     switch ( menuID ) {
  418.         case mApple:
  419.             switch ( menuItem ) {
  420.                 case iAbout:        // bring up alert for About 
  421.                     itemHit = Alert(rAboutAlert, nil);
  422.                     break;
  423.                 default:            // all non-About items in this menu are DAs 
  424.                     // type Str255 is an array in MPW 3 
  425.                     GetItem(GetMHandle(mApple), menuItem, daName);
  426.                     daRefNum = OpenDeskAcc(daName);
  427.                     break;
  428.             }
  429.             break;
  430.         case mFile:
  431.             switch ( menuItem ) {
  432.                 case iClose:
  433.                     DoCloseWindow(FrontWindow());
  434.                     break;
  435.                 case iQuit:
  436.                     Terminate();
  437.                     break;
  438.             }
  439.             break;
  440.         case mEdit:                    // call SystemEdit for DA editing & MultiFinder 
  441.             handledByDA = SystemEdit(menuItem-1);    // since we don’t do any Editing 
  442.             break;
  443.         case mSleep:
  444.             switch ( menuItem ) {
  445.                 case iNoSleep:
  446.                     gSleepVal = 0;
  447.                     break;
  448.                 case i60Ticks:
  449.                     gSleepVal = 60;
  450.                     break;
  451.             }
  452.             break;
  453.     }
  454.     HiliteMenu(0);                    // unhighlight what MenuSelect (or MenuKey) hilited 
  455. } //DoMenuCommand
  456.  
  457.  
  458.  
  459. #pragma segment Main
  460. Boolean DoCloseWindow(window)
  461.     WindowPtr    window;
  462. {
  463.     if ( IsDAWindow(window) )
  464.         CloseDeskAcc(((WindowPeek) window)->windowKind);
  465.     else if ( IsAppWindow(window) )
  466.         CloseWindow(window);
  467.     return true;
  468. } //DoCloseWindow
  469.  
  470.  
  471.  
  472. #pragma segment Main
  473. void Terminate()
  474. {
  475.     WindowPtr    aWindow;
  476.     Boolean        closed;
  477.     
  478.     CloseQueue();        // Clean up interaction with A/ROSE Prep 
  479.     closed = true;
  480.     do {
  481.         aWindow = FrontWindow();                // get the current front window 
  482.         if (aWindow != nil)
  483.             closed = DoCloseWindow(aWindow);    // close this window     
  484.     }
  485.     while (closed && (aWindow != nil));
  486.     if (closed)
  487.         ExitToShell();                            // exit if no cancellation 
  488. } //Terminate
  489.  
  490.  
  491.  
  492. #pragma segment Initialize
  493. void Initialize()
  494. {
  495.     Handle        menuBar;
  496.     long        total, contig;
  497.     EventRecord event;
  498.     short        count, result;
  499.     Ptr            windowP;
  500.  
  501.     InitGraf((Ptr) &qd.thePort);
  502.     InitFonts();
  503.     InitWindows();
  504.     InitMenus();
  505.     TEInit();
  506.     InitDialogs(nil);
  507.     InitCursor();
  508.  
  509.     gInBackground = false;
  510.     gSleepVal = 60;
  511.     
  512.     //    This next bit of code is necessary to allow the default button of our
  513.     //    alert be outlined. 
  514.      
  515.     for (count = 1; count <= 3; count++)
  516.         EventAvail(everyEvent, &event);
  517.     
  518.     SysEnvirons(kSysEnvironsVersion, &gMac);
  519.     
  520.     if (gMac.machineType < 0)
  521.         BigBadError(eWrongMachine);
  522.     
  523.     if (! TrapAvailable(_WaitNextEvent, ToolTrap))
  524.         BigBadError(eWrongMachine);
  525.  
  526.     if ((long) GetApplLimit() - (long) ApplicZone() < kMinHeap)
  527.         BigBadError(eSmallSize);
  528.     
  529.     // ZeroScrap(); 
  530.  
  531.     PurgeSpace(&total, &contig);
  532.     if (total < kMinSpace)
  533.         BigBadError(eNoMemory);
  534.  
  535.     result = AROSEPrep();
  536.     if (result != noErr) {
  537.         if (gTID > 0)            // if we registered with .IPC --
  538.             CloseQueue();         // better clean up - we are going to Exit
  539.  
  540.         BigBadError(result);
  541.     }
  542.     
  543.     windowP = NewPtr(sizeof(WindowRecord)); // we allocate storage ourselves
  544.     if ( windowP == nil )
  545.         BigBadError(eNoWindow);
  546.  
  547.     gMyWindow = GetNewWindow(rWindow, windowP, (WindowPtr) -1);
  548.     ghReset = GetNewControl(rResetBtn, gMyWindow);    // Reset counts button 
  549.     ghSend  = GetNewControl(rSendBtn, gMyWindow);    // Send message button 
  550.     
  551.     if ((ghReset == nil) | (ghSend == nil))
  552.         BigBadError(eNoWindow);
  553.  
  554.     menuBar = GetNewMBar(rMenuBar);            // read menus into menu bar 
  555.     if ( menuBar == nil )
  556.         BigBadError(eNoMemory);
  557.     SetMenuBar(menuBar);                    // install menus 
  558.     DisposHandle(menuBar);
  559.     AddResMenu(GetMHandle(mApple), 'DRVR');    // add DA names to Apple menu 
  560.     DrawMenuBar();
  561.     
  562. } //Initialize
  563.  
  564.  
  565. #pragma segment Main
  566. Boolean IsAppWindow(window)
  567.     WindowPtr    window;
  568. {
  569.     short        windowKind;
  570.  
  571.     if ( window == nil )
  572.         return false;
  573.     else {    // application windows have windowKinds = userKind (8) 
  574.         windowKind = ((WindowPeek) window)->windowKind;
  575.         return (windowKind = userKind);
  576.     }
  577. } //IsAppWindow
  578.  
  579.  
  580. #pragma segment Main
  581. Boolean IsDAWindow(window)
  582.     WindowPtr    window;
  583. {
  584.     if ( window == nil )
  585.         return false;
  586.     else    // DA windows have negative windowKinds 
  587.         return ((WindowPeek) window)->windowKind < 0;
  588. } //IsDAWindow
  589.  
  590.  
  591. #pragma segment Initialize
  592. Boolean TrapAvailable(tNumber,tType)
  593.     short        tNumber;
  594.     TrapType    tType;
  595. {
  596.     if ( ( tType == ToolTrap ) &&
  597.         ( gMac.machineType > envMachUnknown ) &&
  598.         ( gMac.machineType < envMacII ) ) {        // it's a 512KE, Plus, or SE 
  599.         tNumber = tNumber & 0x03FF;
  600.         if ( tNumber > 0x01FF )                    // which means the tool traps 
  601.             tNumber = _Unimplemented;            // only go to 0x01FF 
  602.     }
  603.     return NGetTrapAddress(tNumber, tType) != GetTrapAddress(_Unimplemented);
  604. } //TrapAvailable
  605.  
  606.  
  607. #pragma segment Main
  608. void AlertUser( short error)
  609. {
  610.     short        itemHit;
  611.     Str255        errMsg;
  612.  
  613.     SetCursor(&qd.arrow);
  614.     if ((error>0)&&(error<=kLastErrStr)) {
  615.         GetIndString(errMsg, rErrStrings, error);
  616.         ParamText(errMsg, "", "", "");
  617.     }
  618.     else {
  619.         NumToString(error, &errMsg);
  620.         ParamText("\pUnknown error", errMsg, "", "");
  621.     }
  622.         
  623.     itemHit = Alert(rUserAlert, nil);
  624. } // AlertUser 
  625.  
  626. #pragma segment Main
  627. void BigBadError( short error)
  628. {
  629.     AlertUser(error);
  630.     ExitToShell();
  631. }
  632.  
  633.  
  634. #pragma segment Main
  635. void NumToHex( long n, short d, char *s)   // I hate this @#%@ !
  636.     // s must point to at least d+1 free bytes - returns Pascal String of length d
  637.     // requires d > 0
  638. {
  639.     short c;
  640.     
  641.     s[0] = d;
  642.     do {
  643.         c =  (n & 0x0F) + 48;
  644.         if (c>57)
  645.             c = c+7;
  646.         s[d--] = (char) c;
  647.         n = n>>4;
  648.     } while (d > 0);
  649. }
  650.  
  651. #pragma segment Main
  652. void StringCopy(char *s, char *t)
  653. {
  654.     short n= (*t++ = *s++);
  655.     while (n-- >0)
  656.         *t++ = *s++;
  657. }
  658.  
  659. #pragma segment Initialize
  660. short AROSEPrep()
  661. {
  662.     StringHandle sh;
  663.     Str255 clientName = "?", clientType = "?",
  664.             taskName = "?", taskType = "?";            // wasting lots of RAM, eh ?
  665.  
  666.     
  667.     gServerTID = 0;        // as long as we don't know
  668.     
  669.     sh = GetString(rClientName);
  670.     if (sh != nil)
  671.         StringCopy(*sh,clientName);
  672.     sh = GetString(rClientType);
  673.     if (sh != nil)
  674.         StringCopy(*sh,clientType);
  675.     
  676.     gTID = OpenQueue(0);
  677.     if (gTID == 0) {
  678.         return(eNoAROSE);
  679.     }
  680.     if (!Register_Task (p2cstr(&clientName), p2cstr(&clientType), Machine_Visible)) 
  681.         AlertUser(eRegister);
  682.  
  683.     sh = GetString(rTaskName);
  684.     if (sh != nil)
  685.         StringCopy(*sh,taskName);
  686.     sh = GetString(rTaskType);
  687.     if (sh != nil)
  688.         StringCopy(*sh,taskType);
  689.     if (gServerTID = FindServer(p2cstr(&taskName), p2cstr(&taskType)))
  690.         return(noErr);
  691.     else return(eNoServer);
  692. }
  693.  
  694.  
  695. tid_type FindServer(char *name, char *type)
  696. // compare this with "ShowTasks.c" ! 
  697. {
  698.     short        slot;
  699.      tid_type    tid,        // will be (hopefully) our gServerTID
  700.                 sTID;        // the Name Manager TID for a given slot
  701.     unsigned short    index;
  702.  
  703.     
  704.     if (! AskICCM()) {
  705.         AlertUser(eICCMproblem);
  706.         return 0;
  707.     }
  708.     
  709.     slot = 0;
  710.     tid = 0;
  711.     do {
  712.         index = 0;
  713.         if (sTID = gCards[slot++])
  714.             tid = Lookup_Task (name, type, sTID, &index);
  715.     } while ((tid == 0) && (slot < 16));
  716.     return tid;
  717. }
  718.  
  719.  
  720. Boolean     AskICCM()
  721. {
  722.     Boolean result;
  723.     mMessage    *m;
  724.  
  725.     if (GetICCTID() == 0) 
  726.         return(false);
  727.     
  728.     if ((m = GetMsg ()) == 0)
  729.         return(false);
  730.         
  731.     m -> mTo     = GetICCTID ();
  732.     m -> mCode     = ICC_GETCARDS;
  733.     m -> mDataPtr  = (char *) gCards;
  734.     m -> mDataSize = sizeof (tid_type) * 16;
  735.     Send (m);
  736.     m = Receive (OS_MATCH_ALL, OS_MATCH_ALL, ICC_GETCARDS+1, OS_NO_TIMEOUT, 0);
  737.         
  738.     result = (m -> mStatus == 0);  // slotInfo is in cards[0..15] !
  739.     FreeMsg(m);
  740.     return(result);
  741.         
  742. } //     AskICCM()
  743.  
  744.  
  745. void TaskProcessing()
  746. // Here I am a "client", i.e. all I am interested in is getting back the message I sent
  747. // to the "server" earlier. Presumably, I requested something from the server,
  748. // and he is supposed to come back with the reply. 
  749. {
  750.     GrafPtr savePort;
  751.     mMessage *m;
  752.     
  753.     m = Receive(0L, 0L, 0L, -1L, nil);  // -1L: return without waiting (OS_NO_TIMEOUT)
  754.                                         // nil: no completion routine
  755.                                         
  756. // in A/ROSE this would be:    m = Receive(OS_MATCH_ALL, OS_MATCH_ALL, OS_MATCH_ALL, OS_NO_TIMEOUT);
  757.     if (m) {
  758.         gReceived++;
  759.         if (m->mStatus != 0)    {    // message was considered undeliverable
  760.             AlertUser(eUndeliverable);
  761.             FreeMsg(m);
  762.         }
  763.         else {
  764.             switch (m->mCode)    {
  765.             case DUMMYCODE+1:
  766.                 FreeMsg(m);            // we don't need it any more
  767.                 GetPort(&savePort);
  768.                 SetPort(gMyWindow);
  769.                 InvalRect(&(gMyWindow->portBits.bounds)); // update the counter display
  770.                 SetPort(savePort);
  771.                 break;
  772.             case RESETCODE+1:
  773.                 FreeMsg(m);        // just discard this reply
  774.                 gReceived--;     // and correct the display: we wanted to reset the counts!
  775.                 break;
  776.     
  777.             // handle here all the message codes you specified in your design !
  778.     
  779.                 default:
  780.                     AlertUser(eUnknownMsg);
  781.                     m->mCode |= 0x8000;    // unrecognized message code;
  782.                     m->mStatus = OS_UNKNOWN_MESSAGE; // defined in "managers.h"
  783.                     SwapTID(m);
  784.                     Send (m);    // let know that you don't understand
  785.                     gSent++;
  786.                     break;
  787.             }
  788.         }
  789.         UpdateDisplay();
  790.     }        
  791. }
  792.  
  793.  
  794. void SendaMessage(short msgCode, tid_type msgDest)
  795. {
  796.     mMessage *m;
  797.     
  798.     m = GetMsg();
  799.     if (m == nil)
  800.         AlertUser(eNoMsg);
  801.     else {
  802.         m->mCode = msgCode;
  803.         m->mTo = msgDest;
  804.         // pass along mSData, mOData, mDataPtr, mDataSize as needed
  805.         Send(m);
  806.         gSent++;
  807.         UpdateDisplay();
  808.     }
  809. }
  810.  
  811.  
  812. void UpdateDisplay()
  813. {
  814.     GrafPtr savePort;
  815.  
  816.     GetPort(&savePort);
  817.     SetPort(gMyWindow);
  818.     InvalRect(&(gMyWindow->portBits.bounds));
  819.     SetPort(savePort);
  820. }
  821.